/*
 * Copyright (C) 2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package vip.justlive.easyproxy.server.handler;

import java.util.Map;
import lombok.RequiredArgsConstructor;
import vip.justlive.easyproxy.core.context.RemoteContext;
import vip.justlive.easyproxy.core.context.ServerProxyContext;
import vip.justlive.easyproxy.server.entity.Client;
import vip.justlive.easyproxy.server.entity.Proxy;
import vip.justlive.easyproxy.server.repository.AdminRepository;
import vip.justlive.oxygen.core.net.aio.core.ChannelContext;
import vip.justlive.oxygen.core.net.aio.core.GroupContext;

/**
 * @author wubo
 */
@RequiredArgsConstructor
public class ConnectionUpdater implements Runnable {

  private static final long TIMEOUT = 3000;

  private final GroupContext context;
  private final AdminRepository repository;

  @Override
  public void run() {
    Long now = System.currentTimeMillis();
    for (Map.Entry<Long, ChannelContext> entry : context.getChannels().entrySet()) {
      check(entry.getValue(), now);
    }
  }

  private void check(ChannelContext channel, Long now) {
    RemoteContext remote = RemoteContext.lookup(channel);
    if (remote == null && now - channel.getCreateAt() > TIMEOUT) {
      channel.close();
      return;
    }

    if (remote == null) {
      return;
    }

    Client client = repository.getClient(remote.getKey());
    if (client == null) {
      channel.close();
      return;
    }

    for (Proxy proxy : client.getProxies()) {
      ServerProxyContext spc = remote.find(proxy.getId());
      if (spc == null) {
        spc = new ServerProxyContext().setKey(client.getKey()).setName(proxy.getName())
            .setRemote(proxy.getRemote()).setPort(proxy.getPort()).setId(proxy.getId());
        remote.getProxies().add(spc);
      } else if (!spc.getServer().getGroupContext().isStopped()) {
        continue;
      }
      repository.createProxy(spc, remote);
    }
  }

}
